#include <boost/json.hpp>

namespace autodrive {
namespace perception {

/// @brief
/// @tparam T
/// @param j_str
/// @return
template <typename T>
T json_deserialize(std::string const& j_str) noexcept(false) {
  boost::json::value jv;
  try {
    boost::json::error_code ec;
    jv = boost::json::parse(j_str, ec);
    if (ec) {
      std::string err{"[Throw] parse json string fail: " + ec.message()};
      throw std::runtime_error(err);
    }
    return boost::json::value_to<T>(jv);
  } catch (std::exception const& e) {
    std::string err{"[Throw] parse json string fail:" + std::string(e.what())};
    throw std::runtime_error(err);
  } catch (...) {
    throw std::runtime_error("[Throw] parse json string fail, unexpected!!!");
  }
}

template <typename T>
void json_extract(boost::json::object const& j_root, std::string const& key,
                  T& obj) noexcept(false) {
  if (!j_root.contains(key)) {
    throw std::runtime_error("json has no key: " + key);
  }
  auto const& jv{j_root.at(key)};
  obj = boost::json::value_to<T>(jv);
}

}  // namespace perception
}  // namespace autodrive
